import TranstionList from '@/utils/TransitionList';

/** 列表区间进出保存数据 */
export interface TranstionSelectSave<T> {
	data: T[];
	start: number;
	end: number;
}

/** 列表区间进出类 */
export default class TranstionSelectList<T>{

	private saveList: TranstionList<T> = new TranstionList<T>();
	private start: number;
	private length: number;

	/** 保存的数据 */
	private saveData: TranstionSelectSave<T> | null = null;

	/** 列表字典 */
	private setMap = {
		upEnter: new Set<T>(),
		downEnter: new Set<T>(),
		update: new Set<T>(),
		upRemove: new Set<T>(),
		downRemove: new Set<T>(),
	}

	public get Start() {
		return this.start;
	}
	public set Start(val: number) {
		this.start = val;
	}

	public get Length() {
		return this.length;
	}
	public set Length(val: number) {
		this.length = val;
	}

	/** 往上进入 */
	public get UpEnter() {
		return Array.from(this.setMap.upEnter);
	}

	/** 往下进入 */
	public get DownEnter() {
		return Array.from(this.setMap.downEnter);
	}

	/** 更新列表 */
	public get Update() {
		return Array.from(this.setMap.update);
	}

	/** 往上移除 */
	public get UpRemove() {
		return Array.from(this.setMap.upRemove);
	}

	/** 往下移除 */
	public get DownRemove() {
		return Array.from(this.setMap.downRemove);
	}

	constructor(start: number, length: number) {
		this.start = start;
		this.length = length;
	}

	/** 清空字典 */
	public MapClear(): void {
		const { upEnter, downEnter, update, upRemove, downRemove } = this.setMap;
		upEnter.clear();
		downEnter.clear();
		update.clear();
		upRemove.clear();
		downRemove.clear();
	}

	/** 清空 */
	public Clear(): void {
		this.MapClear();
		this.saveList.Clear();
	}

	/**
	 * 添加一组数据
	 * @param list 要添加的数据组
	 */
	public Push(list: T[]) {
		const { saveList, start, length, setMap, saveData } = this;
		const { upEnter, downEnter, update, upRemove, downRemove } = setMap;
		this.MapClear();
		const end = start + length;
		const selectData = list.slice(start, end);
		saveList.Push(selectData);
		saveList.Enter.forEach(data => {
			if (!saveData) {
				downEnter.add(data);
			} else {
				const oldIndex = saveData.data.indexOf(data);
				if (oldIndex === -1) {
					const index = list.indexOf(data);
					if (index < start) {
						upEnter.add(data);
					} else if (index >= end) {
						downEnter.add(data);
					} else {
						downEnter.add(data);
					}
				}
				else if (oldIndex >= saveData.end) {
					downEnter.add(data);
				} else if (oldIndex < saveData.start) {
					upEnter.add(data);
				}
			}
		});
		saveList.Update.forEach(data => { update.add(data); });
		saveList.Remove.forEach(data => {
			const index = list.indexOf(data);
			if (index < start) {
				upRemove.add(data);
			} else if (index >= end) {
				downRemove.add(data);
			}
		});
		this.saveData = { data: [...list], start, end };
	}

}
